/**
    * Most current edited version of WebProxy for WML.
    *
    *
 *   Given a URL
 *    o Fetch the URL
 *    o Transform all links to use this redirect
 *    o Log where we came from and where we are going
 *
 *   1. Read the incoming parameters
 *    o Parse WebQuilt parameters, remove from query strings.
 *    o The second goal
 *   2. Fetch the URL via Java.
 *    o Take the URL specified by the "replace" parameter.
 *    o Load in the URL, edit the links if it is HTML, spit it back out.
 *
 *   Here is part of a sample logfile:
 *
 *   170     0 1     200 -1   -1   http://www.cs.berkeley.edu
 *   2664    1 2     200 15   -1   http://www.eecs.berkeley.edu/Resguide/soda.staff.shtml
 *   5889    2 3     200 8    -1   http://www.eecs.berkeley.edu/Students/Grad/Affairs/CS/
 *   116718  1 4     200 27   -1   http://www.cs.berkeley.edu/Students/newsgroups.shtml
 *   118450  4 5     200 9    -1   http://www.cs.berkeley.edu/Newspages/
 *
 *
 *   Annotated, here is what it means:
 *
 *   Time From To  Parent Code Link  Frame Method   URL + Query
 *   170     0 1    -1    200  -1    -1      GET    http://www.cs.berkeley.edu
 *   2664    1 2    -1    200  15    -1      GET    http://www.eecs.berkeley.edu/Resguide/soda.staff.shtml
 *   5889    2 3    -1    200  8     -1      GET    http://www.eecs.berkeley.edu/Students/Grad/Affairs/CS/
 *   116718  1 4    -1    200  27    -1      GET    http://www.cs.berkeley.edu/Students/newsgroups.shtml
 *   118450  4 5    -1    200  9     -1      GET    http://www.cs.berkeley.edu/Newspages/
 *
 *
 *   Time   - Time (in msec) that the page was requested, where 0 is the start time.
 *   From   - The transaction ID# of the page where we just came from.
 *              You can think of the transaction ID# as the Nth page we viewed.
 *   To     - The current transaction ID#. Pretty much always increments up by one.
 *   Parent - The TID of this pages frameset, -1 if page is not a frame
 *   Code   - The HTTP response code. 200 means ok, 404 means not found.
 *   Link   - The person clicked on the Nth link on the previous page to get here,
 *              where 0 is the starting link. By default assumes links in <A> tags.
 *              Otherwise, the tag name is included
 *   Frame  - The TID of this pages frameset, -1 if page is not a frame.
 *   Method - The HTTP method used to retrieve the page (e.g. GET or POST)
 *   URL    - The current URL we are at.
 *   Query  - Any query data sent with the request (e.g. CGI arguments)
 *
 * =========================================================================================
 *
 *
 * The WebQuilt Proxy servlet. Logs user interactions with the internet.
 *
 * <P>
 * This software is distributed under the
 * <A HREF="http://guir.cs.berkeley.edu/projects/COPYRIGHT.txt">
 * Berkeley Software License</A>.
 *
 * <PRE>
 * Revisions:  - WebQuilt-v1.0-1.0.0, Feb 01 2001, jheer
 *               Created class, based off of redirect.jsp by jasonh
 *             - WebQuilt-v1.0-2.0.0, Mar 10 2001, jheer
 *               Updated frame handling, introduced WebQuiltLogEntry wrapper
 *             - WebQuilt-v2.0.0-2.0.1, Dec 28 2001, kaow
 *               Code cleanup, updated start pages, added support for toolbox
 *             - WebQuilt Apr 15 2002, kaow
 *               Added support for interdeck WAP logging
 * </PRE>
 *
 * @author  Jeffrey Heer (
 *          <A HREF="mailto:jheer@hkn.eecs.berkeley.edu">jheer@hkn.eecs.berkeley.edu</A>
 *          )
 * @author  Jason Hong (
 *          <A HREF="mailto:jasonh@cs.berkeley.edu">jasonh@cs.berkeley.edu</A>
 *          )
 * @author  Wayne Kao (
 *          <A HREF="mailto:kaow@cs.berkeley.edu">kaow@cs.berkeley.edu</A>
 *          )
 * @since   JDK 1.3
 * @version WebQuilt-v2.0.0-2.0.1, Dec 28 2001
 *
 */
package edu.berkeley.guir.webquilt.proxy;

import java.io.*;
import java.net.*;
import java.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
import edu.berkeley.guir.webquilt.*;
// don't render
// import edu.berkeley.guir.webquilt.web.*;
import HTTPClient.WebQuiltURLConnection;


public class WebProxy extends HttpServlet implements WebQuiltConstants {

    private boolean    debug;      // true if we are in debugging mode
    private String     httpPort;   // insecure HTTP port
    private String     httpsPort;  // secure HTTP port
    private String     startPage;  // path to the start page

// don't render
//    private static HTMLWebBrowser browser; // the browser to render images

    /**
     * One time servlet initialization
     */
    public void init() {

	//// Let servers know that WebQuilt is representing!
//	System.setProperty("http.agent",
//			   "WebQuiltProxy");

	//// Make sure we use a handler that supports SSL
        ////  and deals with cookies for us.
	System.setProperty("java.protocol.handler.pkgs",
			   "HTTPClient");

	//// Read in initialization parameters
	httpPort         = getInitParameter("httpPort");
	httpsPort        = getInitParameter("httpsPort");
	String strDebug  = getServletContext().getInitParameter("debug");
	String logdir    = getServletContext().getInitParameter("logdir");
	String taskdir = getServletContext().getInitParameter("taskdir");

	//// get the start page
	startPage = getServletContext().getInitParameter("startpage");

	//// set the directories
	WebQuiltLib.setTaskDir(taskdir);
	WebQuiltLib.setLogDir(logdir);

	if ( httpPort  == null ) { httpPort  = "80"; }
	if ( httpsPort == null ) { httpsPort = "443"; }

	if ( strDebug.equals("true") ) {
	    debug = true;
	} else {
	    debug = false;
	}

    } //


    /**
     * Handle requests made using HTTP GET
     * @param request the HttpServletRequest
     * @param response the HttpServletResponse
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) {
	doProxy(request, response, false);
    } //


    /**
     * Handle requests made using HTTP POST
     * @param request the HttpServletRequest
     * @param response the HttpServletResponse
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) {
	doProxy(request, response, true);
    } //





    /**
     * Proxy a request.   Handles both HTML and WML
     * Replaces the old doProxy method, doHTMLProxy, and doWMLProxy
     *
     * @param request the HttpServletRequest
     * @param response the HttpServletResponse
     * @param isPost indicates if the request was HTTP POST, if not it was GET
     */

    protected void doProxy(HttpServletRequest request, HttpServletResponse response, boolean isPost) {


	//// --------------------------------------------------------------
	//// WebProxy Phase 0 - determine what type of request is being handled (HTML or WML)
	////   Looks at Content-type

	// Wrapper for all the data we're logging
	WebQuiltLogEntry entry = new WebQuiltLogEntry();
	entry.isPost = isPost;

	// Determine media depending on what type of data the client accepts
	// May want to later replace this with something that lets the client explicitly choose media 
	String media;
	String acceptTypes = request.getHeader("Accept");

	// is WAP phone content
	if ( acceptTypes.indexOf("text/vnd.wap.wml") != -1 ) {
		media = "WAP";

//	} else if (acceptTypes.indexOf("*/*") != -1 || acceptTypes.indexOf("text/html") != -1) {
	} else {
		media = "web";
	}


	//// --------------------------------------------------------------
	//// WebProxy Phase 1 - receive request from client, extract
	////   WebQuilt parameters, and prepare connection to intended
        ////   web destination.
	////
	PrintWriter       out;      // We can either output the page through a writer
	OutputStream      ostream;  //  or a stream. Only ONE of these should be used.
	HttpSession       session;  // the WebQuilt user session
	Hashtable         params;   // WebQuilt parameters (stripped from URL or query)

	//// Variable initialization
	out      = null;
	ostream  = null;
	params   = null;
	session  = request.getSession();

	// debugging code
	/*
	int i = 0;
	System.out.println("---REQUEST DATA---:");
	for (Enumeration enum = request.getHeaderNames() ; enum.hasMoreElements() ; ) {

	    String headerName = (String) enum.nextElement();
	    String header = request.getHeader(headerName);
	    System.out.println(i++ + ". " + headerName + ": " + header);

	}
	*/
	//// Session initialization
	if ( session.isNew() ) {

	    String     strServer;          // URL for insecure proxy
	    String     strSecureServer;    // URL for secure proxy
	    String     server;
	    String     uri;

	    server = request.getServerName();
	    uri    = request.getRequestURI();
	    uri    = uri.substring(0, uri.lastIndexOf("/"));

	    //// Set base server values
	    strServer  = "http://"  + server;
	    if ( !httpPort.equals("80") ) {
		strServer  += ":" + httpPort;
	    }

	    strSecureServer = "https://" + server;
	    if ( !httpsPort.equals("443") ) {
		strSecureServer += ":" + httpsPort;
	    }

	    strServer       = strServer      .toLowerCase() + uri + "/";
	    strSecureServer = strSecureServer.toLowerCase() + uri + "/";

	    //// Initialize the proxy editors
	    if (media.equals("WAP")) {
		// This editor edits all links to point to the proxy
		WMLProxyEdit proxyEdit = new WMLProxyEdit(strServer, strSecureServer);
		WMLGoLinkEditor goEditor = new WMLGoLinkEditor();
		WMLSrcEditor srcEditor = new WMLSrcEditor();
		proxyEdit.registerEditor(goEditor,         WMLProxyEdit.TAG_A     );
		proxyEdit.registerEditor(goEditor,         WMLProxyEdit.TAG_GO    );
		proxyEdit.registerEditor(srcEditor,        WMLProxyEdit.TAG_IMG   );
		proxyEdit.setMode(debug ? WMLProxyEdit.DEBUG_MODE : WMLProxyEdit.DEPLOY_MODE);
		session.setAttribute("EDITOR", proxyEdit);

	    } else {	// is web media
	        // This editor edits all links to point to the proxy
		HTMLProxyEdit proxyEdit = new HTMLProxyEdit(strServer, strSecureServer);
		HTMLLinkEditor linkEditor = new HTMLLinkEditor();
		proxyEdit.registerEditor(linkEditor,               HTMLProxyEdit.TAG_A     );
		proxyEdit.registerEditor(linkEditor,               HTMLProxyEdit.TAG_AREA  );
		proxyEdit.registerEditor(new HTMLRelLinkEditor(),  HTMLProxyEdit.TAG_LINK  );
		proxyEdit.registerEditor(new HTMLFormEditor(),     HTMLProxyEdit.TAG_FORM  );
		proxyEdit.registerEditor(new HTMLFrameEditor(),    HTMLProxyEdit.TAG_FRAME );
		proxyEdit.registerEditor(new HTMLRefreshEditor(),  HTMLProxyEdit.TAG_META  );
		proxyEdit.setMode(debug ? HTMLProxyEdit.DEBUG_MODE : HTMLProxyEdit.DEPLOY_MODE);
		session.setAttribute("EDITOR", proxyEdit);

	    }
	    //// Initialize the session transaction ID.
	    session.setAttribute("TID", new Integer(0));

	    //// Initialize the session start time.
	    session.setAttribute("STARTTIME", new Long(System.currentTimeMillis()));

	    //// Initialize a monitor that will clean up when this
            ////  session expires.
	    session.setAttribute("MONITOR", new ProxySessionMonitor());
	}

	//// Get the proxy's HTML/WML editors
	ProxyEdit proxyEdit;
	if (media.equals("WAP")) {
	    proxyEdit = (WMLProxyEdit) session.getAttribute("EDITOR");

	} else {	// is web media
	    proxyEdit = (HTMLProxyEdit) session.getAttribute("EDITOR");
	}

	//// Read in query string
	if ( isPost ) {
	    try {
		byte[] incoming = WebQuiltLib.readAllFromInputStream(request.getInputStream());
		entry.strQuery  = new String(incoming, 0, incoming.length);
	    } catch ( Exception e ) {
		System.err.println("Caught exception " + e);
		log("Caught exception while sending POST data.\n", e);
	    }
	} else {
	    entry.strQuery = request.getQueryString();
	}

	//// Parse query string
	params = new Hashtable();
	if ( entry.strQuery != null )
	    entry.strQuery = WebQuiltLib.stripWebQuiltParams(entry.strQuery, params);
	else
	    entry.strQuery = "";


	//// Get WebQuilt parameters
	extractParams(entry, params, session);


	//// Check for replace parameter.
	////  If the replace parameter doesn't exist, then show a default page.
	if (entry.strReplace == null) {

        // Depending on what kind of testing, comment the appropriate line.
	    if (media.equals("WAP")) {
		printWMLStartPage(response);

	    } else {	// is web media
		//printPCStartPage(response);
		//printPDAStartPage(response);
		printStartPage(response);
	    }
	    return;

	} else {
	    try {
		ostream  = response.getOutputStream();
	    } catch ( Exception e ) {
		System.err.println("Couldn't open output stream!");
		System.err.println("Caught exception " + e);
		log("Caught exception while opening response output stream.\n", e);
	    }
	}


	//// --------------------------------------------------------------
	//// WebProxy Phase 2 - connect to intended web destination
	////   and proxy the page back to the client.
	////

	URL                    url;                // destination URL
	String                 strUrl = new String();             // string representation of url
	WebQuiltURLConnection  conn = null;        // the HTTP connection
	InputStream            istream;            // stream for server data
	ByteArrayInputStream   istream2;           // stream to proxy editor
	byte[]                 data = null;
	int                    contentLength = -1;

	//// Follow redirects.
	////  We update strReplace later so this is OK.
	HttpURLConnection.setFollowRedirects(true);

	//// Read in the URL.
	try {
	    //// Open up the connection.
	    url = new URL(entry.strReplace);
	    strUrl = url.toExternalForm();

	    try {
		conn = new WebQuiltURLConnection(url, session.getId());
	    } catch ( Exception e ) {
		System.err.println("Caught exception " + e);
		log("Caught Exception while opening HTTP connection.\n", e);
	    }

	    conn.setDoInput(true);
	    conn.setAllowUserInteraction(false);

	    // passing along the browserID to the connection
//	    System.out.println("conn.getRequestProperty(\"User-Agent\")=" + conn.getRequestProperty("User-Agent"));
	    conn.setRequestProperty("User-Agent", request.getHeader("User-Agent"));

	    //// Write POST data, if necessary
	    if ( isPost ) {

		conn.setRequestMethod("POST");
		if ( entry.strQuery.length() > 0 ) {
		    conn.setDoOutput(true);
		    PrintWriter postOut = new PrintWriter(conn.getOutputStream());
		    postOut.print(entry.strQuery);
		    postOut.close();
		}
	    }

	    entry.respCode = conn.getResponseCode();

	    //// Set the appropriate content type
	    entry.contentType = conn.getContentType();
	    if ( entry.contentType != null )
		response.setContentType(entry.contentType);
	    else
		entry.contentType = "";


	    //// Get the content length
	    contentLength = conn.getContentLength();

	    //// If we have an error, get the error input stream.
	    ////  Otherwise, just use the normal input stream.
	    //System.out.println("response code: " + entry.respCode);
	    if (entry.respCode >= 400) {

		istream = conn.getErrorStream();
		if (istream == null)
		    istream = conn.getInputStream();

	    }
	    else {
		istream = conn.getInputStream();
	    }

	    //// Read in all of the data from the webpage.
	    data     = WebQuiltLib.readAllFromInputStream(istream);
	    istream2 = new ByteArrayInputStream(data);

	    //// If we were redirected, we need to update our URL
	    url              = conn.getURL();
	    entry.strReplace = url.toString();

	    //// Generate the base of the page and a query-free URL.
	    entry.strBase = WebQuiltLib.generateBaseHref(entry.strReplace);
	    entry.strOrig = WebQuiltLib.stripQuery(entry.strReplace);

        WMLGoLinkEditor.url = entry.strReplace;

	    //// If the requested document is an html/wml page edit it
	    ////  before proxying, otherwise just send it over.
            if (media.equals("WAP") || entry.contentType.startsWith("text/html")) {

		//// Initialize the proxy editor, then proxy the page
		proxyEdit.init(entry, response);
		proxyEdit.proxyCode(istream2, ostream);

	    } else {
		//// Just send the data through to the client
		WebQuiltLib.connectStreams(istream2, ostream);
	    }
	}
	catch ( Exception e ) {
	    try {
		log("Caught exception while attempting to proxy page.\n", e);
		out = new PrintWriter(ostream);
		out.println("<PRE>");
		e.printStackTrace(out);
		out.println("</PRE>");
	    } catch ( Exception x ) {
		System.err.println("Caught exception " + x);
		log("Caught exception while attempting to proxy page.\n", x);
	    }
	}


	//// --------------------------------------------------------------
	//// WebProxy Phase 3 - Save the HTML/WML file and log the page.
	////

	//// Save cached copy of page and log the transaction.
	try {

	    String             strBaseName = WebQuiltLib.getCachedFileDir(entry.strTaskID, entry.strUserID);
	    String             strPage     = WebQuiltLib.getCachedFileName(entry.strTaskID, entry.strUserID, entry.nextTID);
	    String             strLinks    = strBaseName + entry.nextTID + ".links";
	    String             strImage    = strBaseName + entry.nextTID + ".jpg";
	    String             strLog      = WebQuiltLib.getLogFileName(entry.strTaskID, entry.strUserID);
	    FileOutputStream   fostream;
	    FileWriter         fwtr;

	    ////  First create the directory.
	    File fileSaveDir = new File(strBaseName);
	    if (!fileSaveDir.exists()) {
		fileSaveDir.mkdirs();
	    }

	    //// Save the file locally.
	    if ( contentLength < MAX_CACHED_FILE_SIZE ) {
		//// File is small enough for us to cache.
		istream2 = new ByteArrayInputStream(data);
		fostream = new FileOutputStream(strPage);

		if (media.equals("WAP") || entry.contentType.startsWith("text/html")) {

		    //// Initialize the proxy editor, then proxy the page
		    proxyEdit.proxyCode(istream2, fostream);

		} else {
		    //// Just send the data through to disk
		    WebQuiltLib.connectStreams(istream2, fostream);
		}
		fostream.close();
	    } else {
		//// File too big, so don't cache it. Log the rejection.
		log("Rejected file caching for " + entry.strTaskID + "-" +
		    entry.strUserID + " TID = " + entry.nextTID +
		    ". File size = " + contentLength + ".\n");
	    }

	    //// Make sure we don't store people's passwords!
	    entry.strQuery = WebQuiltLib.blockOutPassword(entry.strQuery);

	    //// Log the page.
        fwtr = new FileWriter(strLog, true);
        //
        // do WAP intercard logging
        if (media.equals("WAP") && entry.strTrackstring != null) {
            int cardFromTID = entry.fromTID;
            
            // all actions that occurred in the deck
            //System.out.println(entry.strTrackstring);
            StringTokenizer deckTokens = new StringTokenizer(entry.strTrackstring, ";", false);

            // all actions that occurred in this particular card 
            StringTokenizer cardTokens;
            WebQuiltLogEntry cardLogEntry;

            // data captured on each card
            String cardFromCard = "none";

            String cardToCard = "none";
            
            String cardLinkID = "0";
            int cardTime = 0;

            while (deckTokens.hasMoreTokens()) {
                cardTokens = new StringTokenizer(deckTokens.nextToken(), "-", false);
                try {
                    //cardFromCard = cardTokens.nextToken();
                    //System.out.println("cardFromCard: " + cardFromCard);

                    cardToCard = cardTokens.nextToken();
                    //System.out.println("cardToCard: " + cardToCard);
                    
                    cardLinkID = cardTokens.nextToken();
                    //System.out.println("cardLinkID: " + cardLinkID);
                    
                    try {
                        cardTime = Integer.parseInt(cardTokens.nextToken());
                        //System.out.println("cardTime: " + cardTime);
                    } catch (Exception e) {
                        cardTime = 0;
                    }
                } catch (Exception e) {
                    // next iteration of while loop
                    continue;
                }

                if (cardToCard.equals("wq_out")) {
                    entry.fromTID = cardFromTID;
                    entry.time = cardTime * 1000;
                    break;
                }

                cardLogEntry = new WebQuiltLogEntry();
                cardLogEntry.parentID = -1;
                cardLogEntry.respCode = -1;
                cardLogEntry.frameID = -1;
                cardLogEntry.isInterCard = true;
                cardLogEntry.strReplace = cardToCard;
                cardLogEntry.strQuery = "";

                cardLogEntry.fromTID = cardFromTID;
                cardFromTID =   // this nextTID will be fromTID for next card
                    cardLogEntry.nextTID = nextTID(session, cardLogEntry);
                cardLogEntry.strLinkID = cardLinkID;

                cardLogEntry.time = cardTime * 1000;
                //System.out.println(cardLogEntry.toString());
                fwtr.write(cardLogEntry.toString());

            }
        // regular page logging
        } //else {
            fwtr.write(entry.toString());
            //fwtr.write(entry.toDebugString());
        //}
        fwtr.close();

	    //// render image of page & save links
// don't render
//	    System.out.println("strPage: " + strPage);
//	    System.out.println("strLinks: " + strLinks);
//	    System.out.println("strImage: " + strImage);
//	    System.out.println("strUrl: " + strUrl);
//	    if (browser==null) {
//		browser = new HTMLWebBrowser(WebQuiltLib.getBrowserWidth(), WebQuiltLib.getBrowserHeight(), strPage);
//	    }
//	    browser.renderPage(strUrl);
//	    browser.saveLinkLocations(true, strLinks);
//	    browser.cleanUp();
//	    browser.saveJPEG(strImage);



	}
	catch (Exception e) {
	    e.printStackTrace();
	    log("Caught exception while writing log entry.\n", e);
	}

    }


    /**
     * This method is responsible for extracting and/or calculating
     *  all the WebQuilt parameters and data needed to successfully
     *  log the page.
     * The extracted data is stored in the specified WebQuiltLogEntry
     *  wrapper.
     * @param entry the LogEntry to store the data in
     * @param params a hashtable containing parameters extracted
     *                from the query string
     * @param session the current user HttpSession
     */
    private void extractParams(WebQuiltLogEntry entry, Hashtable params, HttpSession session) {

	//// Extract destination URL (replace parameter)
	entry.strReplace = getParam(params, PARAM_REPLACE);
	entry.strReplace = WebQuiltLib.prepareReplaceParameter(entry.strReplace);

	//// Extract the referrer page's TID
	String strFromTID = getParam(params, PARAM_TID);
	if (strFromTID == null) {
	    strFromTID = "0";
	}
	//// Extract the link ID
	entry.strLinkID   = getParam(params, PARAM_LINKID);
	if (entry.strLinkID == null) {
	    entry.strLinkID = "-1";
	}
	//// Extract the frame parent ID
	String strParentID = getParam(params, PARAM_PARENTID);
	if (strParentID == null) {
	    strParentID = "-1";
	}
	//// Extract the frame number
	String strFrameID  = getParam(params, PARAM_FRAMEID);
	if (strFrameID == null) {
	    strFrameID = "-1";
	}
	//// Extract taskbox setting
	entry.strTaskBox = getParam(params, PARAM_TASKBOX);

	//// Extract trackstring
	entry.strTrackstring = getParam(params, PARAM_TRACKSTRING);

	//// Extract taskID and user ID
	entry.strTaskID = getParam(params, PARAM_TASKID);
	entry.strUserID = getParam(params, PARAM_USERID);

	//System.out.println("before: "+ session.getAttribute(ATTRIB_TASKID) + ";" + session.getAttribute(ATTRIB_USERID));

	//// Get the taskID and userID
	if ( session.isNew() ) {
	    // if this is a new session, see if the taskID and
	    //  userID were passed to us.
	    if (entry.strTaskID == null)
		entry.strTaskID = DEFAULT_TASK;

	    // if no user id is specified, name the user after the session id
	    if (entry.strUserID == null)
		entry.strUserID = session.getId();

	    // if no task box preference, turn off
            if (entry.strTaskBox == null)
		entry.strTaskBox = "off";

	} else {
	    // if the session has already been established, use
	    //  the saved task and user IDs.
	    if (entry.strTaskID == null)
            	entry.strTaskID = (String)session.getAttribute(ATTRIB_TASKID);
	    if (entry.strUserID == null)
	    	entry.strUserID = (String)session.getAttribute(ATTRIB_USERID);
	    if (entry.strTaskBox == null)
	    	entry.strTaskBox= (String)session.getAttribute(ATTRIB_TASKBOX);
	}

	// Save the IDs for future lookup.
	session.setAttribute(ATTRIB_TASKID, entry.strTaskID);
	session.setAttribute(ATTRIB_USERID, entry.strUserID);
	session.setAttribute(ATTRIB_TASKBOX, entry.strTaskBox);

	//System.out.println("after: "+ session.getAttribute(ATTRIB_TASKID) + ";" + session.getAttribute(ATTRIB_USERID));

	//// If there's no replace param, we're done
	if ( entry.strReplace == null ) {
	    return;
	}

	//// Check if the request is secure or not
	if ( entry.strReplace.startsWith("https://") ) {
	    entry.secure = true;
	} else {
	    entry.secure = false;
	}

	//// Append http protocol if none specified
	if ( !WebQuiltLib.startsWithProtocol(entry.strReplace) ) {
	    entry.strReplace = "http://" + entry.strReplace;
	}

	//// Add the query string, if necessary
	if ( !entry.isPost && entry.strQuery.length() > 0 ) {
	    entry.strReplace += "?" + entry.strQuery;
	}

	//// Parse the current parent ID
	try {
	    entry.parentID = Integer.parseInt(strParentID);
	} catch ( Exception e ) {
	    entry.parentID = -1;
	}

	//// Parse the current frame ID
	try {
	    entry.frameID = Integer.parseInt(strFrameID);
	} catch ( Exception e ) {
	    entry.frameID = -1;
	}

    try {
        entry.fromTID = Integer.parseInt(strFromTID);
    } catch ( Exception e ) {
        entry.fromTID = 0;
    }

    entry.nextTID = nextTID(session, entry);

	//// Get the time spent on the page.
	Long dTime = (Long) session.getAttribute("STARTTIME");
	entry.time = System.currentTimeMillis() - dTime.longValue();
    }


    /**
     * Gets the next available TID
     * @param params the parameter Hashtable
     * @param strParam the parameter to retrieve
     * @return the next available TID
     */
    private int nextTID(HttpSession session, WebQuiltLogEntry entry) {

        //// Set the from tid value to be max of current TID and next TID,
        ////  just in case someone bookmarked the URL or if someone is
        ////  trying to hack the system.
        
    	//// Get the next session transaction ID.
    	Integer nextTIDInteger = (Integer) session.getAttribute("TID");

    	//// Increment the next session transaction ID.
    	////  Store the next session transaction ID.
    	int nextTID = Math.max(nextTIDInteger.intValue(), entry.fromTID) + 1;
    	session.setAttribute("TID", new Integer(nextTID));

        return nextTID;

    }

    /**
     * Retrieves a parsed WebQuilt parameter.
     * @param params the parameter Hashtable
     * @param strParam the parameter to retrieve
     * @return the requested parameter, or null if not present
     */
    private String getParam(Hashtable params, String strParam) {
	String p = (String) params.get(strParam);
	if ( p == null ) {
	    return null;
	} else {
	    	//try {
			return URLDecoder.decode(p);/*, urlCharEncoding);

		} catch (UnsupportedEncodingException e) {
			System.err.println("Cannot decode in " + urlCharEncoding);
			return null;
		}*/
	}
    } //


    /**
     * Prints out the default HTML WebQuilt start page for PCs
     * @param response the servlet response object
     */
    private void printPCStartPage(HttpServletResponse response) {
	try {
	    PrintWriter out = response.getWriter();

	    out.println("<HTML>");
	    out.println("<HEAD><TITLE>WebQuilt Start</TITLE></HEAD>");
	    out.println("<BODY BGCOLOR=\"#FFFFFF\">");
	    out.println("<H1>WebQuilt Start</H1>");
	    out.print("<FORM action=\"");
	    out.print(response.encodeURL(PROXY_FILE));
	    out.println("\">");
	    out.println("<p>");
	    out.println("Please type in a starting page:");
	    out.println("<p>");
	    out.println("<INPUT type=text size=40 name=\"" + PARAM_REPLACE + "\" VALUE=\"http://\">");
	    out.println("<INPUT TYPE=SUBMIT VALUE=\"Go!\">");
	    out.println("<p><SMALL>For example:<br><A HREF=\"");
	    out.print(response.encodeURL(PROXY_FILE));
	    out.print("?" + PARAM_REPLACE + "=http%3A%2F%2Fwww.berkeley.edu\">http://www.berkeley.edu</A></SMALL>");
	    out.println();
	    out.println("</FORM>");
	    out.println("</BODY>");
	    out.println("</HTML>");

	}
	catch ( Exception e ) {
	    System.err.println("Caught exception: " + e);
	}
    } //

    /**
     * Prints out the start page as specified by the web.xml file
     */

    private void printStartPage(HttpServletResponse response) {
	try {
	    BufferedReader in = new BufferedReader(new FileReader(startPage));
	    PrintWriter out = response.getWriter();

	    String line = new String("");
	    while ( (line=in.readLine()) != null) {
		out.println(line);
	    }

	    in.close();
	} catch(IOException e) {
		e.printStackTrace();
	}
    }



        /**
     * Prints out the default HTML WebQuilt start page for PDAs
     * @param response the servlet response object
     */
    private void printPDAStartPage(HttpServletResponse response) {
	try {
	    PrintWriter out = response.getWriter();
	    out.println("<HTML>");
	    out.println("<HEAD> <TITLE>WebQuilt Start</TITLE>");
            out.println("	<meta name=Handheldfriendly content=\"true\">");
            out.println("	<meta name=PalmComputingPlatform content=\"true\">");
            out.println("</HEAD>");
	    out.println("<BODY BGCOLOR=\"#FFFFFF\">");

	}
	catch ( Exception e ) {
	    System.err.println("Caught exception: " + e);
	}
    } //


            /**
     * Prints out the default WML WebQuilt start page
     * @param response the servlet response object
     */
    private void printWMLStartPage(HttpServletResponse response) {
	try {
	    PrintWriter out = response.getWriter();

	    out.println("<?xml version=\"1.0\"?>");

	    out.println("<!DOCTYPE wml PUBLIC \"-//WAPFORUM//DTD WML 1.1//EN\"");
            out.println("\"http://www.wapforum.org/DTD/wml_1.1.xml\">");
	    out.println("<wml>");
	    out.println("   <card title=\"WebQuilt Start Page\">");
	    out.println("       <p>");
	    out.print("             WebQuilt Start<br/>");
	    out.println("                    <a href=\"/webquilt/webproxy?" + PARAM_REPLACE + "=http%3A%2F%2Fwap.google.com/\">Google</a><br/> ");
	    out.println("                    <a href=\"/webquilt/webproxy?" + PARAM_REPLACE + "=http%3A%2F%2Fwap.prnewswire.co.uk/\">PR Newswire</a><br/> ");
	    out.println("                    <a href=\"/webquilt/webproxy?" + PARAM_REPLACE + "=http%3A%2F%2Fwww.amazon.com/phone\">Amazon.com</a><br/> ");
	    out.println("                    <a href=\"/webquilt/webproxy?" + PARAM_REPLACE + "=http%3A%2F%2Fwap.mp3.com/\">MP3.com</a><br/> ");
	    out.println("           <anchor>Other...<go href=\"#other\"/></anchor>");
	    out.println("       </p>");
	    out.println("   </card>");
	    out.println("");
	    out.println("   <card id=\"other\" title=\"Webquilt - Other URL\">");
	    out.println("       <p>");
	    out.println("           URL: <input name=\"url\" size=\"15\"/>");
	    out.println("       </p>");
	    out.println("       <do type=\"accept\" label=\"Go\">");
	    out.println("             <go href=\"http://128.32.131.226/webquilt/webproxy;jsessionid=test?" + PARAM_REPLACE + "=$(url)\"/>");
	    out.println("      </do>");
	    out.println("   </card>");
	    out.println("</wml>");
	}
	catch ( Exception e ) {
	    System.err.println("Caught exception: " + e);
	}
    } //

} // end of class

//==============================================================================

/*
Copyright (c) 2001 Regents of the University of California.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

1. Redistributions of source code must retain the above copyright
   notice, this list of conditions and the following disclaimer.

2. Redistributions in binary form must reproduce the above copyright
   notice, this list of conditions and the following disclaimer in the
   documentation and/or other materials provided with the distribution.

3. All advertising materials mentioning features or use of this software
   must display the following acknowledgement:

      This product includes software developed by the Group for User
      Interface Research at the University of California at Berkeley.

4. The name of the University may not be used to endorse or promote products
   derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
*/
